package com.my.house.service;

import com.my.house.domain.Contract;
import com.my.house.domain.Room;
import lombok.extern.slf4j.Slf4j;
import lombok.RequiredArgsConstructor;
import com.my.house.mapper.ContractMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;

/**
 * <p>
 * 租房合同表 服务实现类
 * </p>
 *
 * @author yangll
 * @since 2025-02-08
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ContractService extends ServiceImpl<ContractMapper, Contract> {

    private final RoomService roomService;

    /**
     * 添加合同（入住）
     * @param userId 用户id
     * @param roomId 房间id
     * @param startDate 开始日期
     * @param endDate 截止日期
     * @param price 每月租金
     * @param lessee 承租人姓名
     * @param lesseeMobile 承租人手机号
     * @param lesseeNo 承租人身份证号
     * @param deposit 押金
     * @param remark 备注
     */
    @Transactional(rollbackFor = Exception.class)
    public void addContract(Long userId, Long roomId, LocalDate startDate, LocalDate endDate,
                           Integer price, String lessee, String lesseeMobile, String lesseeNo,
                           Integer deposit, String remark) {
        // 检查房间是否存在且为空置状态
        Room room = roomService.lambdaQuery()
                .eq(Room::getId, roomId)
                .eq(Room::getUserId, userId)
                .eq(Room::getDeleted, Boolean.FALSE)
                .one();
        if (room == null) {
            throw new RuntimeException("房间不存在");
        }
        if (!room.getEmptyStatus()) {
            throw new RuntimeException("房间已被占用，无法入住");
        }

        // 创建合同
        Contract contract = new Contract();
        contract.setUserId(userId);
        contract.setRoomId(roomId);
        contract.setStartDate(startDate);
        contract.setEndDate(endDate);
        contract.setPrice(price);
        contract.setLessee(lessee);
        contract.setLesseeMobile(lesseeMobile);
        contract.setLesseeNo(lesseeNo);
        contract.setDeposit(deposit);
        contract.setRemark(remark != null ? remark : "");
        contract.setEffective(Boolean.TRUE);
        save(contract);

        // 更新房间状态为非空置
        roomService.lambdaUpdate()
                .eq(Room::getId, roomId)
                .eq(Room::getUserId, userId)
                .set(Room::getEmptyStatus, Boolean.FALSE)
                .update();
    }

    /**
     * 根据房间ID查询有效合同
     * @param userId 用户id
     * @param roomId 房间id
     * @return 合同信息
     */
    public Contract findEffectiveContractByRoomId(Long userId, Long roomId) {
        return lambdaQuery()
                .eq(Contract::getUserId, userId)
                .eq(Contract::getRoomId, roomId)
                .eq(Contract::getEffective, Boolean.TRUE)
                .eq(Contract::getDeleted, Boolean.FALSE)
                .one();
    }

    /**
     * 根据ID查询合同
     * @param userId 用户id
     * @param id 合同id
     * @return 合同信息
     */
    public Contract findById(Long userId, Long id) {
        return lambdaQuery()
                .eq(Contract::getId, id)
                .eq(Contract::getUserId, userId)
                .eq(Contract::getDeleted, Boolean.FALSE)
                .one();
    }

    /**
     * 退房（使合同失效，房间状态改为空置）
     * @param userId 用户id
     * @param roomId 房间id
     */
    @Transactional(rollbackFor = Exception.class)
    public void checkout(Long userId, Long roomId) {
        // 查找有效合同
        Contract contract = findEffectiveContractByRoomId(userId, roomId);
        if (contract == null) {
            throw new RuntimeException("未找到有效合同");
        }

        // 使合同失效
        lambdaUpdate()
                .eq(Contract::getId, contract.getId())
                .eq(Contract::getUserId, userId)
                .set(Contract::getEffective, Boolean.FALSE)
                .update();

        // 更新房间状态为空置
        roomService.lambdaUpdate()
                .eq(Room::getId, roomId)
                .eq(Room::getUserId, userId)
                .set(Room::getEmptyStatus, Boolean.TRUE)
                .update();
    }
}
